package com.lcxw.hxzbapi.controller.roomcontroller;

import com.alibaba.fastjson.JSONObject;
import com.lcxw.hxzbapi.entity.pojo.YwpdMember;
import com.lcxw.hxzbapi.service.YwpdMemberService;
import com.lcxw.hxzbcommon.entity.ErrorCode;
import com.qiniu.rtc.RtcRoomManager;
import com.qiniu.util.Auth;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.lcxw.hxzbapi.entity.pojo.YwpdRoom;
import com.lcxw.hxzbapi.entity.response.Response;
import com.lcxw.hxzbapi.service.AttentionService;
import com.lcxw.hxzbapi.service.YwpdRoomService;
import com.lcxw.hxzbcommon.common.RedisUtils;
import com.lcxw.hxzbcommon.common.RoomUtils;
import com.lcxw.hxzbcommon.common.StringUtil;
import com.lcxw.hxzbcommon.common.qiniu.RoomConfig;
import com.lcxw.hxzbcommon.common.qiniu.PiliException;

@RestController
@RequestMapping("/api/room")
@CrossOrigin
@Validated
public class RoomController {

    private Logger logger = LoggerFactory.getLogger(RoomController.class);

    @Resource
    YwpdRoomService ywpdRoomService;

    @Resource
    YwpdMemberService ywpdMemberService;

    @Resource
    RoomRealization roomRealization;

    @Resource
    Qiniu qiniu;

    @Resource
    AttentionService attentionService;

    @Resource
    RedisUtils redisUtils;

    private Auth auth = Auth.create(RoomConfig.ACCESS_KEY, RoomConfig.SECRET_KEY);
    private RtcRoomManager rmanager = new RtcRoomManager(auth);

    //1、主持人进入房间接口
    @PostMapping("/join/manager")
    public Response managerJoinRoom(@RequestBody JSONObject requestParams) {
        long userId = Long.parseLong(requestParams.getString("userId"));
//        long roomId = Long.parseLong(requestParams.getString("roomId"));
        String roomType = requestParams.getString("roomType");
        String roomName = requestParams.getString("roomName");
        String roomNotice = requestParams.getString("roomNotice");
        String longitude = requestParams.getString("longitude");//经度
        String latitude = requestParams.getString("latitude");//纬度
        String city = requestParams.getString("city");//直播地点，城市
        logger.info("manager {} join to room,roomType set to {}.", userId, roomType);

        YwpdMember ywpdMember;
        YwpdRoom ywpdRoom;
        long roomId;

        try {

            //判断是否已经实名认证
            ywpdMember = ywpdMemberService.selectYwpdMemberByUserId(userId);
            if (0 == ywpdMember.getRealNameAuth()) {
                return Response
                    .common(logger, "该用户还未实名认证", ErrorCode.NO_PERMISSION_SUPPLEMENT, "该用户还未实名认证",
                        null);
            }

            //如果是 paipai 类型的，则需要签约，判断是否签约用户
            if ("paipai".equals(roomType) && ywpdMember.getSign() == 0) {
                return Response.common(logger, "拍拍房间必须是签约主播才能开启", 3004, "拍拍房间必须是工会签约主播才能开启", null);
            }

            ywpdRoom = ywpdRoomService.selectRoomByUserId(userId);

            //如果该用户暂时还没有房间，则创建房间
            if (null == ywpdRoom) {
                ywpdRoom = roomRealization.createRoom(userId);
            }
            roomId = ywpdRoom.getRoomId();

            //判断该房间是否被禁播
            if (2 == ywpdRoom.getLiveStatus()) {
                return Response.common(logger, "该房间已被禁播", ErrorCode.NO_PERMISSION, "该房间已被禁播", null);
            }

            ywpdRoom.setLiveStatus(1);
            if (!StringUtil.isEmpty(roomName)) {
                ywpdRoom.setRoomName(roomName);
            }
            if (!StringUtil.isEmpty(roomNotice)) {
                ywpdRoom.setRoomNotice(roomNotice);
            }
            ywpdRoom.setRoomType(roomType);
//            ywpdRoom.setLongitude(longitude);
//            ywpdRoom.setLatitude(latitude);
            ywpdRoom.setCity(city);

            ywpdRoomService.updateRoom(ywpdRoom);

        } catch (Exception e) {
            return Response.dbFail(logger, "房间操作失败，数据库操作失败");
        }

        String roomToken = null;

        //如果不是全屏直播，则需要生成roomToken
        if (!"fullVideo".equals(roomType)) {

            Date date = new Date();
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.add(Calendar.DATE, 1);
            date = cal.getTime();
            long expireAt = date.getTime() / 1000;

            try {
                roomToken = rmanager
                    .getRoomToken(RoomConfig.RTC_APPID, roomId + "", userId + "", expireAt,
                        "admin");
            } catch (Exception e) {
                return Response
                    .common(logger, "生成roomToken失败。", ErrorCode.INTERNAL_ERROR, "生成roomToken失败",
                        null);
            }

        }

        //在redis中初始化数据
        roomRealization.initRoom(roomId, userId);

        if ("paipai".equals(roomType)) {
            roomRealization.initBaodeng(roomId);
        }

        //构造响应
        JSONObject data = new JSONObject();
        List rewards;
        try {
            rewards = roomRealization.getReward(roomId);
            if (null != rewards) {
                if (rewards.size() > 3) {
                    rewards = rewards.subList(0, 3);
                }
            }
        } catch (Exception e) {
            return Response.dbFail(logger, "从数据库中获取打赏数据失败");
        }
        int fire = roomRealization.getFire(roomId);

        logger.info("房间开播，房间号：{}", roomId);
        data.put("reward", rewards);
        data.put("fire", fire);
        data.put("roomToken", roomToken);
        data.put("roomInfo", ywpdRoom);

        return Response.ok(data);

    }

    //2、观众进入房间
    @PostMapping("/join/viewer")
    public Response viewerJoin(@RequestBody JSONObject requestParams) {
        long userId = Long.parseLong(requestParams.getString("userId"));
        long roomId = Long.parseLong(requestParams.getString("roomId"));
        logger.info("用户 {} 进入房间 {}.", userId, roomId);

        try {
            //从七牛云获取当前直播状态，如果获取不到则没有开播
            qiniu.getLiveStatus(roomId);
        } catch (PiliException e) {
            return Response
                .common(logger, "进入房间失败，房间暂未开播", ErrorCode.INVALID_PARAM, "房间暂未开播", null);
        }

        YwpdRoom ywpdRoom;
        String roomToken = null;
        try {
            ywpdRoom = ywpdRoomService.selectRoomByRoomId(roomId);
            //判断该房间是否被禁播
            if (2 == ywpdRoom.getLiveStatus()) {
                return Response.common(logger, "该房间已被禁播", ErrorCode.NO_PERMISSION, "该房间已被禁播", null);
            }

            //判断房间直播类型，如果不是全屏直播，则需要生成roomToken
            if (!"fullVideo".equals(ywpdRoom.getRoomType())) {
                Date date = new Date();
                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.add(Calendar.DATE, 1);
                date = cal.getTime();
                long expireAt = date.getTime() / 1000;
                roomToken = rmanager
                    .getRoomToken(RoomConfig.RTC_APPID, roomId + "", userId + "", expireAt, "user");
            }

        } catch (Exception e) {
            return Response.dbFail(logger, "房间操作失败，数据库操作失败");
        }

        //判断是会否关注了该房间
        int isAttention = 0;
        try {
            List<Long> attentionRoomList = attentionService.getAttentionRoombyUserId(userId);
            if (attentionRoomList.contains(roomId)) {
                isAttention = 1;
            }

        } catch (Exception e) {
            logger.error("获取关注的房间号失败。");
        }

        //在redis中的该用户观众中加入观众
        roomRealization.redisAddViewers(roomId, userId);
        roomRealization.viewersChange(roomId);
        int fire = roomRealization.getFire(roomId);

        JSONObject data = new JSONObject();

        data.put("roomToken", roomToken);
        data.put("fire", fire);
        data.put("isAttention", isAttention);
        data.put("roomInfo", ywpdRoom);
        List rewards = null;
        try {
            rewards = roomRealization.getReward(roomId);
            if (null != rewards) {

                if (rewards.size() > 3) {
                    rewards = rewards.subList(0, 3);
                }
            }
        } catch (Exception e) {
            logger.error("从数据库中获取打赏数据失败");
        }
        data.put("reward", rewards);
        return Response.ok(data);
    }

    //3、退出直播间，包含主持人和观众
    @PostMapping("/quit")
    public Response quitRoom(@RequestBody JSONObject requestParams) {
        long userId = Long.parseLong(requestParams.getString("userId"));
        long roomId = Long.parseLong(requestParams.getString("roomId"));
        if (StringUtil.isEmpty(requestParams.getString("roomId"))) {
            return Response.wrongParam(logger, "roomId");
        }
        Response response = new Response();
        //生成房间观众的redisKey
        String roomViewer_redisKey = RoomUtils.get_roomViewer_redisKey(roomId);

        try {
            YwpdRoom ywpdRoom = ywpdRoomService.selectRoomByRoomId(roomId);
            long userIdQueried = ywpdRoom.getUserId();
            //如果是主持人退出，需要操作的
            if (userId == userIdQueried) {
                //房间状态置为0
                ywpdRoom.setLiveStatus(0);
                //数据库中更新房间信息
                ywpdRoomService.updateRoom(ywpdRoom);
                //redis中清除房间的连麦信息
                roomRealization.clearRoomCache(roomId);
                logger.info("主持人下播，房间号：{}", roomId);
            } else {
                //如果是观众退出房间，则需要操作的
                redisUtils.set_remove(roomViewer_redisKey, userId + "");

                roomRealization.deleteApplyAndLineUser(roomId, userId);

                roomRealization.viewersChange(roomId);

            }
        } catch (Exception e) {
            return Response.dbFail(logger, "operate room");
        }

        response.setCode(0);
        response.setDesc("success");

        return response;
    }

    /**
     * 获取房间观众列表的接口
     */
    @PostMapping("/viewers/get")
    public Response getRoomViewers(@RequestBody JSONObject requestBody) {
        String roomId = requestBody.getString("roomId");
        Set<String> roomViewers = roomRealization.getRoomViewers(roomId);
        return Response.ok(roomViewers);
    }

    /**
     * 获取房间打赏榜单的接口
     */
    @PostMapping("/rewards/get")
    public Response getRoomRewards(@RequestBody JSONObject requestBody) {
        long roomId = Long.parseLong(requestBody.getString("roomId"));
        List<Object> rewards;
        try {
            rewards = roomRealization.getReward(roomId);
        } catch (Exception e) {
            return Response.dbFail(logger, "获取打赏榜单失败");
        }
        return Response.ok(rewards);
    }

}